﻿namespace BathroomLocator.Services.Models
{
	using System;
	using System.ComponentModel;
	using System.ComponentModel.DataAnnotations;
	using System.Globalization;
	using System.Web.Security;

	public class LogOnModel
	{
		[Required]
		[DisplayName("User name")]
		public string UserName { get; set; }

		[Required]
		[DataType(DataType.Password)]
		[DisplayName("Password")]
		public string Password { get; set; }

		[DisplayName("Remember me?")]
		public bool RememberMe { get; set; }
	}

	[PropertiesMustMatch("Password", "ConfirmPassword", ErrorMessage = "The password and confirmation password do not match.")]
	public class RegisterModel
	{
		[Required]
		[DisplayName("User name")]
		public string UserName { get; set; }

		[Required]
		[DataType(DataType.EmailAddress)]
		[DisplayName("Email address")]
		public string Email { get; set; }

		[Required]
		[ValidatePasswordLength]
		[DataType(DataType.Password)]
		[DisplayName("Password")]
		public string Password { get; set; }

		[Required]
		[DataType(DataType.Password)]
		[DisplayName("Confirm password")]
		public string ConfirmPassword { get; set; }
	}

	[AttributeUsage(AttributeTargets.Class, AllowMultiple = true, Inherited = true)]
	public sealed class PropertiesMustMatchAttribute : ValidationAttribute
	{
		private const string DefaultErrorMessage = "'{0}' and '{1}' do not match.";
		private readonly object typeId = new object();

		public PropertiesMustMatchAttribute(string originalProperty, string confirmProperty)
			: base(DefaultErrorMessage)
		{
			this.OriginalProperty = originalProperty;
			this.ConfirmProperty = confirmProperty;
		}

		public string ConfirmProperty { get; private set; }

		public string OriginalProperty { get; private set; }

		public override object TypeId
		{
			get
			{
				return this.typeId;
			}
		}

		public override string FormatErrorMessage(string name)
		{
			return string.Format(CultureInfo.CurrentUICulture, this.ErrorMessageString, this.OriginalProperty, this.ConfirmProperty);
		}

		public override bool IsValid(object value)
		{
			PropertyDescriptorCollection properties = TypeDescriptor.GetProperties(value);
			object originalValue = properties.Find(this.OriginalProperty, true /* ignoreCase */).GetValue(value);
			object confirmValue = properties.Find(this.ConfirmProperty, true /* ignoreCase */).GetValue(value);

			return object.Equals(originalValue, confirmValue);
		}
	}

	[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property, AllowMultiple = false, Inherited = true)]
	public sealed class ValidatePasswordLengthAttribute : ValidationAttribute
	{
		private const string DefaultErrorMessage = "'{0}' must be at least {1} characters long.";
		private readonly int minCharacters = Membership.Provider.MinRequiredPasswordLength;

		public ValidatePasswordLengthAttribute()
			: base(DefaultErrorMessage)
		{
		}

		public override string FormatErrorMessage(string name)
		{
			return string.Format(CultureInfo.CurrentUICulture, this.ErrorMessageString, name, this.minCharacters);
		}

		public override bool IsValid(object value)
		{
			var valueAsString = value as string;

			return (valueAsString != null) && (valueAsString.Length >= this.minCharacters);
		}
	}
}
